/* Copyright Andy Mitchell 2007. No warranties */

function ThreadList(gtdinboxPage){
	this.gtdinboxPage = gtdinboxPage;
	this._threads = [];
	this._threadsHashId = {};
	this._threadsHashRow = {};
	this._noSubject = "gtdnosubject";
	this._noSubjectRegExp = /^\s*\([^)]+\)\s*$/;
	this._multiToOne = new MultiToOne(this.gtdinboxPage, 5000);
}

ThreadList.prototype.getThreadById = function(id){
	if( this._threadsHashId[id] ) return this._threadsHashId[id];
};

ThreadList.prototype.getThreadByRow = function(subject, snippetFromHTML, namesArray){
	// Retrieve the subject first. If multiple ones found; discern first on snippet; and then on author. 
	
	
	//this.gtdinboxPage.unsafeWindow.console.log("getThreadByRow: " + subject);
	var threads = this._threadsHashRow[subject];
	if( !threads && this._noSubjectRegExp.test(subject) ) threads = this._threadsHashRow[this.noSubject];	// 'subject' could be (no subject)
	
	//this.gtdinboxPage.unsafeWindow.console.log("Tested Subject:");
	//this.gtdinboxPage.unsafeWindow.console.log(threads);
	
	if( !threads ) return;
	if( threads.length==1 ) return threads[0];
	
	// Try to distinguish on author
	if( !(namesArray instanceof Array) ) namesArray = [namesArray];
	var threads2 = [];
	for( var i = 0; i < threads.length; i++ ){
		if( threads[i].testNames(namesArray) ) threads2.push(threads[i]);
	}

	//this.gtdinboxPage.unsafeWindow.console.log("Tested Names:");
	//this.gtdinboxPage.unsafeWindow.console.log(threads2);

	if( threads2.length==0 ) return;
	if( threads2.length==1 ) return threads2[0];
	
	// Now try to decipher. HTML snippet can be shorter than real snippet. So, tokenise words in HTML snippet and see if they're found in other snippet. 
	// TODO Fails on search; because it doesn't reveal the last message
	var threads3 = [];
	for( var i = 0; i < threads2.length; i++ ){
		if( threads2[i].testSnippet(snippetFromHTML) ) threads3.push(threads2[i]);
	}
	
	//this.gtdinboxPage.unsafeWindow.console.log("Tested Snippet:");
	//this.gtdinboxPage.unsafeWindow.console.log(threads3);
	
	if( threads3.length==1 ) return threads3[0];
	
};

ThreadList.prototype.parseAjaxResponse = function(a){
	var thread = null;
	var found = false;
	for( var i = 0; i < a.length; i++ ){
		if( a[i][0]==="tb" ){	// it's a set of 10 rows; relating to UI row data
			for( var j = 3; j < a[i].length; j++ ){
				var titem = a[i][j];
				if( thread = this._threadsHashId[titem[0]] ){	// exists
					thread.update("tb", titem);
				}else{	// create
					thread = new Thread(this, titem[0], "tb", titem);
					this.addThread(thread);
				}
				this.addToSubjectHash(thread);
			}
			found = true;
		}else if( a[i][0]==="cs" ){	// start of a block of message data items (cs is conversation)
			var titem = a[i];
			if( this._threadsHashId[titem[1]] ){
				thread = this._threadsHashId[titem[1]];
			}else{
				thread = new Thread(this, titem[1]);
				this.addThread(thread);
			}
			found = true;
		}else if( a[i][0]==="ms" ){
			var titem = a[i];
			if( thread ){
				thread.update("ms", titem);
				if( !a[i+1] || a[i+1][0]!="ms" ){	// this is last msg in thread; so subject/snippet is correct
					thread.checkAutoLabel();
				}
			}
			this.addToSubjectHash(thread);
			found = true;
		}else{
			thread = null;
		}
	}
	if( found ){
		this._multiToOne.process("update-threads", GIPROTOTYPE.bind(this, this.syncDbAll) );
	}
};

ThreadList.prototype.syncDbAll = function(){
	// We currently store labels against contacts (and threads); but only when we label/unlabel.
	// If a new user replies to a thread, or we forward it, they should also be associated with the label.
	// So, when a thread updates, we re-sync names with db.
try{
	var j = 0;
	for( var i = 0; i < this._threads.length; i++ ){
		var t = this._threads[i];
		if( t.labels.length > 0 && !t.syncedDbSinceUpdate ){
			t.syncDb();
			j++;
		}
	};
	this.gtdinboxPage.unsafeWindow.console.log("syncDbAll: " + j);
}catch(e){
	if( GTDDEBUGMODE ) alert("ThreadList syncDbAll\n" + e.toString());
}
};

ThreadList.prototype.addThread = function(thread, incSubject){
	this._threads.push(thread);
	this._threadsHashId[thread.id] = thread;
};
ThreadList.prototype.addToSubjectHash = function(thread){
	var subject = thread.subject || this._noSubject;
	if( !subject ) return;
	var a = null;
	if( a = this._threadsHashRow[subject] ){
		for( var i = 0; i < a.length; i++ ) if(a[i]==thread) return;
		this._threadsHashRow[subject].push(thread);
	}else{
		this._threadsHashRow[subject] = [thread];
	}
};

ThreadList.prototype.destroy = function(){
};